#include <filesystem>
#include <fstream>
#include "console_output_strategy.h"
#include "file_output_strategy.h"
#include "io_manager.h"
#include "gtest/gtest.h"

namespace Base {
namespace SystemLog {
namespace {
constexpr const char* TEST_LOG_DIR = "out/tests/logs";
constexpr const char* TEST_MESSAGE = "Hello, IO Manager!\n";

std::string ReadFileContent(const std::string &path) {
    std::ifstream file(path);
    if (!file.is_open()) {
        return "";
    }
    return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
}
} // namespace

class IOMangerTest : public testing::Test {
public:
    static void SetUpTestCase(void);
    static void TearDownTestCase(void);
    void SetUp();
    void TearDown();
};

void IOMangerTest::SetUpTestCase(void)
{}

void IOMangerTest::TearDownTestCase(void)
{}

void IOMangerTest::SetUp(void)
{
    std::filesystem::create_directories(TEST_LOG_DIR);
}

void IOMangerTest::TearDown(void)
{
    try {
        if (std::filesystem::exists(TEST_LOG_DIR)) {
            std::filesystem::remove_all(TEST_LOG_DIR);
        } else {
            GTEST_LOG_(ERROR) << "directory does not exist: " << TEST_LOG_DIR << '\n';
        }
    } catch (const std::filesystem::filesystem_error &ex) {
        GTEST_LOG_(ERROR) << "deletion failed: " << ex.what() << '\n';
    }
}

/**
 * @tc.name: IOMangerTest_001
 * @tc.desc: verify multiple strategies function.
 * @tc.type: FUNC
 */
TEST_F(IOMangerTest, IOMangerTest_001)
{
    IOManager manager;
    manager.AddStrategy(std::make_unique<ConsoleOutputStrategy>());
    FileOutputOptions options;
    options.filePathPattern = std::string(TEST_LOG_DIR) + "/io_manager_test.log";
    manager.AddStrategy(std::make_unique<FileOutputStrategy>(options));

    ASSERT_EQ(manager.Write(TEST_MESSAGE, strlen(TEST_MESSAGE)), ERR_OK);
    ASSERT_EQ(manager.Flush(), ERR_OK);

    auto content = ReadFileContent(options.filePathPattern);
    ASSERT_EQ(content, TEST_MESSAGE);
}
} // namespace SystemLog
} // namespace Base
